package bancosys.tec.services.testcase;

import java.io.IOException;

import jmine.tec.environment.db.DBEnvironment;
import jmine.tec.services.environment.DigesterPostscriptEntryLoader;
import jmine.tec.services.environment.RefDBEnvironment;
import jmine.tec.services.environment.ServicePostscriptEntryLoader;
import jmine.tec.test.testcase.DBTestCase;
import bancosys.tec.persist.authorization.AuthorizationStatus;
import bancosys.tec.persist.dao.BeanNotFoundException;
import bancosys.tec.utils.db.descriptor.FlatReferenceDatabaseBuilder.ReferenceDatabaseDescriptionType;
import bancosys.tec.utils.db.descriptor.ReferenceDatabaseEntry;
import bancosys.tec.utils.db.executor.CouldNotExecuteException;

/**
 * Este tescase sabe importar a base de referência com arquivos db.xml.
 * 
 * @author wagner
 */
public abstract class RefDBTestCase extends DBTestCase {

    static {
        DBEnvironment.register(new ServicePostscriptEntryLoader());
        DBEnvironment.register(new DigesterPostscriptEntryLoader());
    }

    private AuthorizationStatus previousAuthorizationStatus;

    public RefDBTestCase() {
        super();

    }

    public RefDBTestCase(String name) {
        super(name);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void oncePerTestCaseClass() {
        if (!(this.getEnvironment() instanceof RefDBEnvironment)) {
            RefDBEnvironment env = new RefDBEnvironment(this.getEnvironment());
            this.setEnvironment(env);
        }
        super.oncePerTestCaseClass();
    }

    /**
     * Instancia um ambiente.
     * 
     * @return um ambiente.
     */
    @Override
    protected DBEnvironment instantiateEnvironment() {
        DBEnvironment delegate = super.instantiateEnvironment();
        return new RefDBEnvironment(delegate);
    }

    /**
     * Inicializa a transação caso o controle transacional seja interno e desativa a autorização.
     * 
     * @throws Exception em qquer caso de erro.
     */
    @Override
    public void setUp() throws Exception {
        super.setUp();
        this.previousAuthorizationStatus = this.getHelper().getThreadAuthorizationStatus();
        this.getHelper().setThreadAuthorizationStatus(AuthorizationStatus.DISABLED);
    }

    /**
     * caso o controle transacional seja externo, finaliza a transação; caso contrário, limpa o banco de dados. Reativa a authorização.
     * 
     * @throws Exception em qquer caso de erro.
     */
    @Override
    public void tearDown() throws Exception {
        this.getHelper().setThreadAuthorizationStatus(this.previousAuthorizationStatus);
        super.tearDown();
    }

    /**
     * Descreve o que deve ser executado.
     * 
     * @return Um {@link ReferenceDatabaseDescriptionType}
     */
    @Override
    public ReferenceDatabaseDescriptionType getReferenceDatabaseDescriptionType() {
        return ReferenceDatabaseDescriptionType.ALL;
    }

    /**
     * Executa serviços de uma planilha.
     * 
     * @param fileName nome do arquivo.
     * @throws IOException exceção.
     * @throws CouldNotExecuteException exceção.
     */
    protected final void executa(String processorName, String fileName) throws IOException {
        ((RefDBEnvironment) this.getEnvironment()).executaTransacional(processorName, fileName, true);
    }

    /**
     * {@inheritDoc}
     */
    protected void executa(ReferenceDatabaseEntry entry) throws Throwable {
        ((RefDBEnvironment) this.getEnvironment()).executa(entry);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void initializeTestData() throws BeanNotFoundException {
        // vazio
    }

}